package fans_group

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/olivere/elastic/v7"
	"github.com/spf13/cast"
	global2 "longmen/server/config/global"
	"longmen/server/internal/rpc/tencentim/fans_group/fans_messages"
	"longmen/server/internal/rpc/tencentim/utils"
	"longmen/server/pkg/common/api_models"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/redis/cache"
	"reflect"
	"time"
)

type FansGroupHistory struct {
	Seq         int64                     `json:"seq"`          //  消息ID （Seq + 群ID  删除指定消息）
	Uid         int                       `json:"uid"`          // 发送用户ID
	GroupId     string                    `json:"group_id"`     // 群ID
	NickName    string                    `json:"nick_name"`    // 昵称
	Avatar      string                    `json:"avatar"`       // 头像
	Content     string                    `json:"content"`      // 发送的内容
	SendTime    int64                     `json:"send_time"`    // 发送事件
	Type        fans_messages.MsgSendType `json:"type"`         // 消息类型 0-普通文本消息 1-加入提示 2-撤回 3-删除 4-被踢出 5-被禁言 6-解禁 7-图文消息
	Role        int                       `json:"role"`         // 角色 0-群员 1-管理 2-群主 3-机器人
	ImageUrl    string                    `json:"image_url"`    // 图文消息的图片链接
	ImageWidth  int                       `json:"image_width"`  // 图文消息的图片宽度
	ImageHeight int                       `json:"image_height"` // 图文消息的图片高度
}

func (h FansGroupHistory) getEsIndexName() string {
	return fmt.Sprintf("fans_group_history")
}
func (h FansGroupHistory) writeToEsAndMQ(ctx context.Context) error {
	_, err := global2.GetEs().Index().Index(h.getEsIndexName()).Id(cast.ToString(h.Seq)).BodyJson(h).Do(ctx)
	if err != nil {
		return err
	}

	return h.WriteMq()
}

func (h FansGroupHistory) WriteMq() error {
	return global2.PublishFansGroup.BroadCast(h)
}

func (h FansGroupHistory) WriteToEsAndMQ(ctx context.Context) error {
	return h.writeToEsAndMQ(ctx)
}

func (f *fansGroup) writeChatHistory(rawBytes []byte) bool {
	req := fans_messages.SayRepMessage{}
	err := json.Unmarshal(rawBytes, &req)
	if err != nil {
		return false
	}
	if f.user == nil {
		return false
	}

	gcUser, err := db_main.GetGroupChatUser(map[string]interface{}{
		"user_id":       f.user.UserId,
		"fans_group_id": f.req.GroupId,
	})
	if err != nil {
		global2.Log.Error(err)
		return false
	}

	content := req.Resp.Content.Decode()
	err = FansGroupHistory{
		Seq:         f.req.MsgSeq,
		Uid:         f.user.UserId,
		GroupId:     f.req.GroupId,
		NickName:    f.user.ClientName,
		Avatar:      f.user.Avatar,
		Content:     content,
		SendTime:    f.req.MsgTime,
		Type:        req.Resp.Type,
		Role:        gcUser.Role,
		ImageUrl:    req.Resp.ImageUrl,
		ImageWidth:  req.Resp.ImageWidth,
		ImageHeight: req.Resp.ImageHeight,
	}.writeToEsAndMQ(f.ctx)

	//记录最近消息
	latestMsg := content
	if len(req.Resp.ImageUrl) >= 0 {
		latestMsg = "[图片]"
	}

	//写入最近消息
	cache.SetGroupChatLatestMsg(f.req.GroupId, &api_models.GroupChatLatestMsg{
		FansGroupId:      f.req.GroupId,
		LatestMsgTime:    time.Now().Unix(),
		LatestMsg:        latestMsg,
		FromUserId:       f.user.UserId,
		FromUserNickname: f.user.ClientName,
	})

	if err != nil {
		return false
	}

	return true
}

func (h FansGroupHistory) getHistory(groupID []string, page, limit int, delStamp int64) ([]FansGroupHistory, int64) {
	start := (page - 1) * limit
	// 聊天排序，查询时按倒序分页, 查出来后再reverse,得出的数据就是按时间正序，最后一条就是最新的
	sort := elastic.NewFieldSort("send_time").Desc()
	query := elastic.NewBoolQuery().Filter(elastic.NewTermsQuery("group_id", utils.EsTermsTransSlice(groupID)...))
	if delStamp > 0 {
		query.Filter(elastic.NewRangeQuery("send_time").Gt(delStamp))
	}
	res, err := global2.GetEs().Search(h.getEsIndexName()).
		From(start).
		Size(limit).
		PostFilter(query).
		SortBy(sort).
		Do(context.Background())
	if err != nil {
		global2.Log.Errorf("search error: %v", err)
		return nil, 0
	}
	var item FansGroupHistory
	records := make([]FansGroupHistory, 0)
	for _, v := range res.Each(reflect.TypeOf(item)) {
		records = append(records, v.(FansGroupHistory))
	}
	//reverse
	for i, j := 0, len(records)-1; i < j; i, j = i+1, j-1 {
		records[i], records[j] = records[j], records[i]
	}
	return records, res.TotalHits()
}

func (h FansGroupHistory) delHistory(ctx context.Context, seq string) error {
	_, err := global2.GetEs().Delete().Index(h.getEsIndexName()).Id(seq).Refresh("true").Do(ctx)
	if err != nil {
		global2.Log.Errorf("delete error: %v", err)
		return err
	}
	return nil
}

// DelHistory 删除聊天记录 SEQ + 群ID
func DelHistory(ctx context.Context, seq string) error {
	return FansGroupHistory{}.delHistory(ctx, seq)
}

// UpdateHistory 更新记录 SEQ + 群ID
func UpdateHistory(ctx context.Context, seq string, updateFields map[string]interface{}) error {
	_, err := global2.GetEs().Update().
		Index(FansGroupHistory{}.getEsIndexName()).
		Id(seq).
		Doc(updateFields).
		Refresh("true").
		Do(ctx)
	if err != nil {
		global2.Log.Errorf("delete error: %v", err)
		return err
	}
	return nil
}

func GetFromEs(seq string) (h *FansGroupHistory, err error) {
	h = &FansGroupHistory{}
	res, err := global2.GetEs().Get().Index(h.getEsIndexName()).
		Id(seq).
		Do(context.Background())
	if err != nil {
		return
	}
	err = json.Unmarshal(res.Source, h)
	return
}

func SearchUserHistoryImage(userId int, fansGroupId string) (records []FansGroupHistory, err error) {
	filter := elastic.NewBoolQuery()
	filter = filter.Filter(
		elastic.NewTermsQuery("uid", userId),
		elastic.NewTermQuery("group_id", fansGroupId),
		elastic.NewTermsQuery("type", fans_messages.ImageTextType),
	)
	res, err := global2.GetEs().Search(FansGroupHistory{}.getEsIndexName()).
		From(0).
		Size(100).
		PostFilter(filter).
		Query(filter).
		Do(context.Background())
	var item FansGroupHistory
	records = make([]FansGroupHistory, 0)
	for _, v := range res.Each(reflect.TypeOf(item)) {
		tmp, ok := v.(FansGroupHistory)
		if !ok {
			continue
		}
		if len(tmp.ImageUrl) > 0 {
			records = append(records, tmp)
		}
	}
	return
}

func DeleteUserHistory(userId int, fansGroupId string) (err error) {
	filter := elastic.NewBoolQuery()
	filter.Filter(
		elastic.NewTermsQuery("uid", userId),
		elastic.NewTermQuery("group_id", fansGroupId),
	)
	_, err = global2.GetEs().DeleteByQuery().
		Index(FansGroupHistory{}.getEsIndexName()).
		Query(filter).
		Refresh("true").
		Do(context.Background())
	return err
}
